package org.jvending.registry;

import org.jvending.registry.hibernate.HibernateRepositoryAdaptor;
import org.jvending.registry.hibernate.impl.ServletHibernateRepositoryAdaptee;

import javax.servlet.ServletContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.logging.Logger;

public class ServletRepositoryLoader implements RepositoryLoader {

    private ServletContext servletContext;

    private RepositoryRegistry repositoryRegistry;

    private static Logger logger = Logger.getLogger("ServletRepositoryLoader");

    public ServletRepositoryLoader(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    public void setRepositoryRegistry(RepositoryRegistry repositoryRegistry) {
        this.repositoryRegistry = repositoryRegistry;
    }

    /**
     *
     * @param fileUri a URL, file system path or war file
     * @param repositoryClass
     * @param initParams
     * @return
     * @throws IOException
     */
    public Repository loadRepository(String fileUri, String repositoryClass, Hashtable initParams) throws IOException {
        Hashtable props = (initParams != null) ? initParams : new Hashtable();

        if (fileUri == null || fileUri.trim().equals("")) throw new IOException("File uri must be provided.");
        if (repositoryClass == null || repositoryClass.trim().equals(""))
            throw new IOException("Repository class name must be provided: File Name = " + fileUri
                    + ", Properties = " + props.toString());

        Repository repository = null;

        InputStream inputStream = servletContext.getResourceAsStream(fileUri);
            if(inputStream == null) {
                logger.severe("Could not find " + fileUri);
                throw new IOException("Could not find " + fileUri);
            }

        String message = "File Name = " + fileUri +
                ", Repository Class = " + repositoryClass + ", Properties = " + props.toString();

        try {
            Class c = Class.forName(repositoryClass);
            repository = (Repository) c.newInstance();
            if(repository instanceof HibernateRepositoryAdaptor) {
                ServletHibernateRepositoryAdaptee adaptee = new ServletHibernateRepositoryAdaptee(servletContext);
                ((HibernateRepositoryAdaptor) repository).setHibernateRepositoryAdaptee(adaptee);
            }
            repository.setRepositoryRegistry(repositoryRegistry);
            repository.load(inputStream, props);
        } catch (IOException e) {
            throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
        } catch (Exception e) {
            throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
        } catch (Error e) {
            throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
        }
        return repository;
    }

    public String getLoaderName() {
        return this.getClass().getName();
    }
}
